package cn.thr.ymcc.service.impl;

import cn.thr.ymcc.constant.Cos;
import cn.thr.ymcc.domain.CourseOrder;
import cn.thr.ymcc.domain.CourseOrderItem;
import cn.thr.ymcc.dto.*;
import cn.thr.ymcc.mapper.CourseOrderItemMapper;
import cn.thr.ymcc.mapper.CourseOrderMapper;
import cn.thr.ymcc.service.ICourseOrderService;
import cn.thr.ymcc.util.AssertUtil;
import cn.thr.ymcc.util.CodeGenerateUtils;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.rocketmq.client.producer.TransactionSendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.mockito.internal.util.StringUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author thr
 * @since 2023-03-09
 */
@Service
public class CourseOrderServiceImpl extends ServiceImpl<CourseOrderMapper, CourseOrder> implements ICourseOrderService {

    @Autowired
    private CourseOrderItemMapper courseOrderItemMapper;
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;


    /**
     * 秒杀下单
     * @param orderDto
     * @return
     */
    @Override
    public String killPlaceOrder(OrderDto orderDto) {
        //1.执行下订单业务之前，先校验redis 里面中是否存在token 这个key  执行完要删除这个key
        AssertUtil.isTrue(StringUtils.hasText(orderDto.getToken()),"非法操作");
        AssertUtil.isTrue(redisTemplate.hasKey(orderDto.getToken()),"请不要重复提交");
        //订单编号不能为空
        AssertUtil.isTrue(StringUtils.hasText(orderDto.getOrderNo()),"订单编号不能为空！");

        //2.从redis 中通过订单编号为key  获取预创订单对象
        PreOrder preOrder = (PreOrder) redisTemplate.opsForValue().get(orderDto.getOrderNo());

        //3.封装一个courseOrder 对象
        CourseOrder courseOrder = new CourseOrder();
        //4.courseOrder复制preOrder 实体类
        BeanUtils.copyProperties(preOrder,courseOrder);
        //5.订单对象
        courseOrder.setDiscountAmount(orderDto.getDiscountAmount());
        courseOrder.setPayAmount(courseOrder.getTotalAmount().subtract(orderDto.getDiscountAmount()));
        courseOrder.setPayType(orderDto.getPayType());
        courseOrder.setOrderType(orderDto.getType());

        //6.订单明细对象
        CourseOrderItem courseOrderItem = new CourseOrderItem();
        //7.courseOrderItem复制preOrder 实体类
        BeanUtils.copyProperties(preOrder,courseOrderItem);

        courseOrderItem.setAmount(courseOrder.getTotalAmount());
        //8.推送站内信息
//        MessageDto messageDto = new MessageDto();
//        messageDto.setTitie("下单成功");
//        List<String> courseName = orderDto.getCourseOrderItems().stream().map(courseOrderItem -> courseOrderItem.getCourseName()).collect(Collectors.toList());
//        messageDto.setContent("亲爱的用户您好,你购买的"+String.join(".",courseName)+orderSn+",请尽快付费");
//
//        //站类消息
//        messageDto.setStationDotList(Arrays.asList(
//                new MessageDto.StationDto(orderDto.getLoginId(), "订单消息")
//        ));
//
//        Message<String> message = MessageBuilder.withPayload(JSON.toJSONString(messageDto)).build();
//        //发站内信
//        rocketMQTemplate.sendOneWay(
//                Cos.Message.TOPIC_MESSAGE+":"+Cos.Message.TAGS_MESSAGE_STATION,
//                message
//        );

        /**
         * 9.rocketMQTemplate.sendMessageInTransaction  发送事务请求
         * 第一个参数：事务消息生产的名称
         * 第二个参数：是事务消息的主题和标签  就是发送的目的地
         * 第三个参数：消息内容是发送给消费者的内容
         * 第四个参数：额外参数，是发给事务监听器的  保存订单和订单明细
         */
        //第三个参数  封装要发送给消费者的内容
        PayOrderDto payOrderDto = new PayOrderDto()
                .setAmount(courseOrder.getPayAmount())
                .setPayType(courseOrder.getPayType())
                .setOrderNo(courseOrder.getOrderNo())
                .setSubject(courseOrder.getTitle())
                .setUserId(courseOrder.getUserId())
                .setExtParams("courseIds="+ courseOrderItem.getCourseId());


        // 封装第四个参数 ： CourseOrder实体类中添加一个临时参数（当前订单的明细条目集合）
        courseOrder.setCourseOrderItems(Arrays.asList(courseOrderItem));

        TransactionSendResult transactionSendResult = rocketMQTemplate.sendMessageInTransaction(
                //事务监听器的名字
                Cos.pay.TX_PRODUCER_GROUP_PAY_ORDER,
                //主题和标签  主题:标签
                Cos.pay.TOPIC_TX_PAY_ORDER+":"+Cos.pay.TAGS_TX_PAY_ORDER,
                //消息用来保存支付单
                MessageBuilder.withPayload(JSON.toJSONString(payOrderDto)).build(),
                //额外参数
                courseOrder
        );

        //10.删除redis 这个token
        redisTemplate.delete(orderDto.getToken());

        //11.下单成功，通过订单编号从redis中删除预创订单
        redisTemplate.delete(orderDto.getOrderNo());

        return orderDto.getOrderNo();
    }


    @Override
    public String placeOrder(OrderDto orderDto) {
        //执行下订单业务之前，先校验redis 里面中是否存在token 这个key  执行完要删除这个key
        AssertUtil.isTrue(StringUtils.hasText(orderDto.getToken()),"非法操作");
        AssertUtil.isTrue(redisTemplate.hasKey(orderDto.getToken()),"请不要重复提交");
        //封装一个主表对象
        CourseOrder courseOrder = new CourseOrder();
        courseOrder.setDiscountAmount(orderDto.getDiscountAmount());
        courseOrder.setUserId(orderDto.getLoginId());
        //设置订单编号
        String orderSn = CodeGenerateUtils.generateOrderSn(orderDto.getLoginId());
        courseOrder.setOrderNo(orderSn);
        courseOrder.setTitle("普通订单");
        
        //统计总金额、总数量
        Double totalAmount = 0D;
        Integer totalCount = 0;
        for (CourseOrderItem courseOrderItem : orderDto.getCourseOrderItems() ) {
            totalAmount += courseOrderItem.getPrice().doubleValue() * courseOrderItem.getCount();
            totalCount += courseOrderItem.getCount();
        }
        courseOrder.setTotalAmount(new BigDecimal(totalAmount));
        courseOrder.setTotalCount(totalCount);

        //支付金额 = 总金额 - 优惠金额
        courseOrder.setPayAmount(new BigDecimal(totalAmount-orderDto.getDiscountAmount().doubleValue()));

        //保存订单主表数据，返回主键
       // baseMapper.insert(courseOrder);

        //2.处理订单明细条目
//        for (CourseOrderItem courseOrderItem : orderDto.getCourseOrderItems() ) {
//            courseOrderItem.setOrderNo(orderSn);
//            courseOrderItem.setAmount(new BigDecimal(courseOrderItem.getPrice().doubleValue() * courseOrderItem.getCount()));
//            courseOrderItem.setOrderId(courseOrder.getId());
//            courseOrderItemMapper.insert(courseOrderItem);
//        }

        //3.推送站内信息
//        MessageDto messageDto = new MessageDto();
//        messageDto.setTitie("下单成功");
//        List<String> courseName = orderDto.getCourseOrderItems().stream().map(courseOrderItem -> courseOrderItem.getCourseName()).collect(Collectors.toList());
//        messageDto.setContent("亲爱的用户您好,你购买的"+String.join(".",courseName)+orderSn+",请尽快付费");
//
//        //站类消息
//        messageDto.setStationDotList(Arrays.asList(
//                new MessageDto.StationDto(orderDto.getLoginId(), "订单消息")
//        ));
//
//        Message<String> message = MessageBuilder.withPayload(JSON.toJSONString(messageDto)).build();
//        //发站内信
//        rocketMQTemplate.sendOneWay(
//                Cos.Message.TOPIC_MESSAGE+":"+Cos.Message.TAGS_MESSAGE_STATION,
//                message
//        );

        /**
         * 4.rocketMQTemplate.sendMessageInTransaction  发送事务请求
         * 第一个参数：事务消息生产的名称
         * 第二个参数：是事务消息的主题和标签  就是发送的目的地
         * 第三个参数：消息内容是发送给消费者的内容
         * 第四个参数：额外参数，是发给事务监听器的  保存订单和订单明细
         */
        //把list 从long 转为 string 类型
        List<String> courseIds = orderDto.getCourseIds().stream().map(cid ->cid.toString()).collect(Collectors.toList());
        //第三个参数  封装要发送给消费者的内容
        PayOrderDto payOrderDto = new PayOrderDto()
                .setAmount(courseOrder.getPayAmount())
                .setPayType(courseOrder.getPayType())
                .setOrderNo(orderSn)
                .setSubject(courseOrder.getTitle())
                .setUserId(courseOrder.getUserId())
                .setExtParams("courseIds="+ String.join(",",courseIds));


        // 封装第四个参数 ： CourseOrder实体类中添加一个临时参数（当前订单的明细条目集合）
        courseOrder.setCourseOrderItems(orderDto.getCourseOrderItems());

        TransactionSendResult transactionSendResult = rocketMQTemplate.sendMessageInTransaction(
                //事务监听器的名字
                Cos.pay.TX_PRODUCER_GROUP_PAY_ORDER,
                //主题和标签  主题:标签
                Cos.pay.TOPIC_TX_PAY_ORDER+":"+Cos.pay.TAGS_TX_PAY_ORDER,
                //消息用来保存支付单
                MessageBuilder.withPayload(JSON.toJSONString(payOrderDto)).build(),
                //额外参数
                courseOrder
        );

        //4。删除redis 这个token
        redisTemplate.delete(orderDto.getToken());

        return orderSn;
    }
    /**
     * 修改订单状态为已支付
     * @param paySuccessDto
     */
    @Transactional
    @Override
    public void paySuccess(PaySuccessDto paySuccessDto) {
        //查到一个订单
        CourseOrder courseOrder = baseMapper.selectOne(new QueryWrapper<CourseOrder>().
                eq("order_no", paySuccessDto.getOrderNo()));
        //判断支付状态
        if(courseOrder.getStatusOrder() == 0){
            //如果订单状态仍然等于0 仍然是支付状态 才修改
            courseOrder.setStatusOrder(1);
            baseMapper.updateById(courseOrder);
        }

    }
    /**
     * 订单服务，支付超时处理
     * @param orderNo
     */
    @Transactional
    @Override
    public void payTimeout(String orderNo) {
        CourseOrder courseOrder = baseMapper.selectOne(new QueryWrapper<CourseOrder>()
                .eq("order_no", orderNo));

        //判断订单是否为0 如果还是为0的话就修改为4（订单超时或失败）
        if(courseOrder.getStatusOrder() ==0){
            courseOrder.setStatusOrder(4);
            baseMapper.updateById(courseOrder);
        }
    }

    @Transactional
    @Override
    public boolean save(CourseOrder courseOrder) {
        //保存订单主表数据，返回主键
         baseMapper.insert(courseOrder);

        //2.处理订单明细条目
        for (CourseOrderItem courseOrderItem : courseOrder.getCourseOrderItems() ) {
            courseOrderItem.setOrderNo(courseOrder.getOrderNo());
            courseOrderItem.setAmount(new BigDecimal(courseOrderItem.getPrice().doubleValue() * courseOrderItem.getCount()));
            courseOrderItem.setOrderId(courseOrder.getId());
            courseOrderItemMapper.insert(courseOrderItem);
        }
        return true;
    }
}
